package ca.mcgill.model.functional.generator;

import ca.mcgill.model.functional.FiniteStateMachine;
import ca.mcgill.model.functional.State;
import ca.mcgill.model.functional.Transition;
import ca.mcgill.model.implementation.ImplementationModel;
import ca.mcgill.model.implementation.Task;
import ca.mcgill.model.implementation.Transaction;

public class ModelValidation {

	public boolean isModelValid(ImplementationModel implModel) {

		for (FiniteStateMachine fsm : implModel.getImplementedNetwork()
				.getFsms()) {

			for (Transition trans : fsm.getTransitions()) {

				if (trans.getSrcState() == null) {
					System.out.println("There is transition that has no source state");
					return false;
				}

				if (trans.getDstState() == null) {
					System.out.println("There is transition with no destination state");
					return false;
				}

//				if (trans.getOutE() == null) {
//					System.out.println("There is transition with no output event");
//					return false;
//				}

				if (trans.getTrigE() == null) {
					System.out.println("There is transition with no triggering event");
					return false;
				}

//				if (trans.getDstState() == trans.getSrcState()
//						&& fsm.getStates().size() > 1) {
//					System.out
//							.println("There is transition where its destination and source transitions are the same");
//					return false;
//				}								
			}
		}

		for (FiniteStateMachine fsm : implModel.getImplementedNetwork()
				.getFsms()) {

			for (State state : fsm.getStates()) {

				if (state.getInTransition() == null) {
					return false;
				}

				if (state.getOutTransitions() == null) {
					return false;
				}

			}

		}
		
		if(!checkInternalEvents(implModel)){
			System.out.println("There is problem with internal events");
		}

		return true;
	}
	
	
	private boolean checkInternalEvents(ImplementationModel implModel){
		
		for(Transaction transaction : implModel.getTransactions()){
			
			for(int i = 0; i < transaction.getTasksInTransaction().size() - 1; i++){
				
				Task task = transaction.getTasksInTransaction().get(i);
				Task nextTask = transaction.getTasksInTransaction().get(i+1);
				
				FiniteStateMachine fsm = task.getFsm();
				FiniteStateMachine nextFsm = nextTask.getFsm();
				
				for(Transition transition : nextFsm.getTransitions()){
					
					boolean exists = false;
					
					for(Transition prevTrans : fsm.getTransitions()){
						
						if(transition.getTrigE() == prevTrans.getOutE()){
							exists = true;
							break;
						}
						
					}
					
					if(!exists){
						return false;
					}
				}
				
			}
			
		}
		
		return true;
		
	}

}
